package main

// http :8084/monitor?key=hyuknbggsddrfgjk
//	connectsions: 2; net speed: 2.45MB/s; net bytes: 123456789;
//	connect: 123.987.234.23; net speed: 1.23MB/s; net bytes: 123456789;
//	connect: 123.987.234.23; net speed: 1.23MB/s; net bytes: 123456789;

import (
	"bytes"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"sync"
	"time"
)

type Monitor struct {
	mutex sync.Mutex

	// 静态的数据用于接口返回
	connCount int
	totoal    ConnMon
	connList  map[net.Conn]ConnMon
	// 静态时间戳
	TimeStamp time.Time

	// 动态的数据用于计算
	d_connCount int
	d_totoal    ConnMon
	d_connList  map[net.Conn]ConnMon
}

type ConnMon struct {
	connSpeed float64
	connBytes int64
}

func (m *Monitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// 判断key是否正确
	if r.FormValue("key") != "hyuknbggsddrfgjk" {
		w.Write([]byte("key error\r	"))
		return
	}

	m.mutex.Lock()
	defer m.mutex.Unlock()
	str := fmt.Sprintf("connectsions: %d; net speed: %.2fMB/s; net bytes: %s;\r", m.connCount, m.totoal.connSpeed, comma(m.totoal.connBytes))
	for k, v := range m.connList {
		str += fmt.Sprintf("connect: %s; net speed: %.2fMB/s; net bytes: %s;\r", k.RemoteAddr().String(), v.connSpeed, comma(v.connBytes))
	}
	w.Write([]byte(str))
}

func comma(n int64) string {
	var buf bytes.Buffer
	s := strconv.FormatInt(n, 10)
	l := len(s)
	if l <= 3 {
		return s
	}
	for i, v := range s {
		if (l-i)%3 == 0 && i != 0 {
			buf.WriteByte(',')
		}
		buf.WriteRune(v)
	}
	return buf.String()
}

func (m *Monitor) Init() {
	m.connList = make(map[net.Conn]ConnMon)
	m.d_connList = make(map[net.Conn]ConnMon)

	go m.Update()

	http.Handle("/monitor", m)
	go http.ListenAndServe(":8084", nil)
}

func (m *Monitor) AddConn(conn net.Conn) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 判断是否已经存在
	if _, ok := m.d_connList[conn]; ok {
		return
	}
	m.d_connCount++
	m.d_connList[conn] = ConnMon{}
}

func (m *Monitor) DelConn(conn net.Conn) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 判断是否已经存在
	if _, ok := m.d_connList[conn]; !ok {
		return
	}
	m.d_connCount--
	delete(m.d_connList, conn)
}

func (m *Monitor) AddBytes(conn net.Conn, n int) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 判断是否已经存在
	v, ok := m.d_connList[conn]
	if !ok {
		log.Printf("add bytes cannot find conn (conn addr=%s)\r\n", conn.RemoteAddr().String())
		return
	}
	m.d_totoal.connBytes += int64(n)
	v.connBytes += int64(n)
	m.d_connList[conn] = v
}

// 每秒钟更新一次
func (m *Monitor) Update() {
	// 一直循环
	for {
		// 休眠1秒钟
		time.Sleep(time.Second)

		m.mutex.Lock()
		currentTime := time.Now()
		timeDiff := currentTime.Sub(m.TimeStamp)
		// 计算速度
		for k, v := range m.d_connList {
			v.connSpeed = float64(v.connBytes-m.connList[k].connBytes) / 1024 / 1024 / float64(timeDiff.Seconds())
			m.d_connList[k] = v
		}
		m.d_totoal.connSpeed = float64(m.d_totoal.connBytes-m.totoal.connBytes) / 1024 / 1024 / float64(timeDiff.Seconds())

		// 更新数据
		m.connCount = m.d_connCount
		m.totoal = m.d_totoal
		m.TimeStamp = currentTime
		m.connList = make(map[net.Conn]ConnMon)
		for k, v := range m.d_connList {
			m.connList[k] = v
		}
		m.mutex.Unlock()
	}
}
